package com.hbx.aspect;

import com.hbx.utils.DFAUtil;
import com.hbx.utils.Result;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.BindingResult;

import java.lang.reflect.Field;
import java.util.Set;
import java.util.stream.Collectors;

/*
 * @Author:hbx
 * 
 * */
@Aspect
@Component
@Order(3)
public class SensitiveFilterAspect {

    @Value("${sensitive.config.template}")
    private String template;

    @Autowired
    private DFAUtil dfaUtil;

    @Pointcut("@annotation(com.hbx.aspect.annotation.SensitiveFilter)")
    public void pointcut(){

    }
    @Around(value = "pointcut()")
    public Object sensitiveFilter(ProceedingJoinPoint point) throws Throwable {
        Object[] args = point.getArgs();
        for (Object arg : args) {
            // 跳过BindingResult
            if (arg instanceof BindingResult) {
                continue;
            }
            Class<?> clazz = arg.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Object value = field.get(arg);
                if (!ObjectUtils.isEmpty(value)){
                    Set<String> map = dfaUtil.getSensitiveWordByDFAMap(value.toString(), 2);
                    if (!CollectionUtils.isEmpty(map)) {
                        Set<String> limit = map.stream()
                                .limit(4)
                                .collect(Collectors.toSet());
                        String msg = String.join(",", limit);
                        Result<String> result = new Result<>();
                        result.setCode(201).setMsg(template.replace("[1]", msg));
                        return result;
                    }
                }
            }
        }
        return point.proceed();
    }
}
